#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include "../source/server.hpp"

using namespace std;

static size_t Split(const std::string &str, const std::string &seq, std::vector<std::string> *results)
{
    size_t offset = 0;
    while (offset < str.size())
    {
        size_t pos = str.find(seq, offset);
        if (pos == std::string::npos)
        {
            // if (pos == str.size())
            //     break;
            results->emplace_back(str.substr(offset));
            return results->size();
        }

        if (pos == offset)
        {
            offset = pos + seq.size();
            continue;
        }
        results->emplace_back(str.substr(offset, pos - offset));
        offset = pos + seq.size();
    }
    return results->size();
}

static bool ReadFile(const std::string &filename, std::string *buf)
{
    std::ifstream ifs(filename, std::ios::binary);
    if (!ifs.is_open())
    {
        ERR_LOG("open %s file error", filename.c_str());
        ifs.close();
        return false;
    }

    size_t fsize = 0;
    ifs.seekg(0, ifs.end); // 文件指针移到末尾位置
    fsize = ifs.tellg();
    ifs.seekg(0, ifs.beg); // 文件指针移到起始位置
    buf->resize(fsize);
    ifs.read(&(*buf)[0], buf->size());
    if (ifs.good() == false)
    {
        ERR_LOG("read %s file error", filename.c_str());
        ifs.close();
        return false;
    }
    ifs.close();
    return true;
}

static bool WriteFile(const std::string &filename, const std::string &buf)
{
    std::ofstream ofs(filename, std::ios::binary | std::ios::trunc);
    if (!ofs.is_open())
    {
        ERR_LOG("open %s file error", filename.c_str());
        ofs.close();
        return false;
    }

    ofs.write(buf.c_str(), buf.size());
    if (ofs.good() == false)
    {
        ERR_LOG("write %s file error", filename.c_str());
        ofs.close();
        return false;
    }
    ofs.close();
    return true;
}

static std::string UrlEncode(const std::string &url, bool convert_space_to_plus)
{
    std::string ret;
    for (auto &c : url)
    {
        if (c == '.' || c == '-' || c == '_' || c == '~' || isalpha(c) || isdigit(c))
        {
            ret += c;
            continue;
        }
        if (c == ' ' && convert_space_to_plus == true)
        {
            ret += '+';
            continue;
        }

        char tmp[4] = {0};
        snprintf(tmp, 4, "%%%02X", c);
        ret += tmp;
    }
    return ret;
}

static char HexToI(char c)
{
    if (c >= '0' && c <= '9')
        return c - '0';
    else if (c >= 'a' && c <= 'f')
        return c - 'a' + 10;
    else if (c >= 'A' && c <= 'F')
        return c - 'A' + 10;
    else
        return -1;
}

// url解码
static std::string UrlDecode(const std::string &url, bool convert_plus_to_space)
{
    std::string ret;
    for (int i = 0; i < url.size(); i++)
    {
        if (url[i] == '+' && convert_plus_to_space == true)
        {
            ret += ' ';
            continue;
        }
        if (url[i] == '%')
        {
            char v1 = HexToI(url[i + 1]);
            char v2 = HexToI(url[i + 2]);
            char v = v1 * 16 + v2;
            ret += v;
            i += 2;
            continue;
        }
        ret += url[i];
    }

    return ret;
}

static bool ValidPath(const std::string &path)
{
    // 根据‘/’分割路径 计算目录深度 如果深度小于0 则路径不合法
    std::vector<std::string> dirs;
    Split(path, "/", &dirs);
    int level = 0;
    for (auto &dir : dirs)
    {
        if (dir == "..")
        {
            level--;
            if (level < 0)
                return false;
        }
        else
            level++;
    }
    return true;
}

int main()
{

    std::string path = "/1/../2";
    cout << ValidPath(path) << endl;
    // string str = ",,,,,,,,,,,,,,,,,,,";
    // vector<string> ret;
    // string seq = ",";
    // Split(str, seq, &ret);
    // for (auto &s : ret)
    // {
    //     cout << "[" << s << "]" << endl;
    // }

    // std::string filename = "makefile";
    // string buf;
    // bool ret = ReadFile(filename, &buf);
    // if (ret == false)
    // {
    //     cout << "read file error" << endl;
    //     return 0;
    // }
    // ret = WriteFile("newfile.txt", buf);
    // if (ret == false)
    // {
    //     cout << "write file error" << endl;
    //     return 0;
    // }

    // string url = "C++";
    // string ret = UrlEncode(url, false);
    // string tmp = UrlDecode(ret, false);
    // cout << "[" << ret << "]" << endl;
    // cout << "[" << tmp << "]" << endl;

    return 0;
}